# -*- coding: utf-8 -*-
import hashlib
from api import api, ERROR_USER, GlobalError
from datetime import datetime
from flask import jsonify, request
from model.answer import Answer
from model.comment import Comment
from model.problem import Problem
from model.studio import Studio
from model.studio_comment import StudioComment
from model.user import User
from util.auth import get_weibo_access_token, get_weibo_info
from util.time_converter import datetime_to_timestamp
from util.user_helper import get_user_or_studio_from_id
from werkzeug.exceptions import NotFound
import json

from flask.ext.login import login_user, logout_user, login_required

class Error:
    REGISTER_PARAMETER_INVALID = {
        'err': ERROR_USER + 1,
        'msg': 'Register Parameter Invalid'
    }
    USER_GENDER_INVALID = {
        'err': ERROR_USER + 2,
        'msg': 'User Gender Invalid'
    }
    INFO_UPDATE_FAILURE = {
        'err': ERROR_USER + 3,
        'msg': 'Info Update Failure'
    }
    LOGIN_PARAMETER_INVALID = {
        'err': ERROR_USER + 4,
        'msg': 'Login Parameter Invalid'
    }
    USER_EXISTS = {
        'err': ERROR_USER + 5,
        'msg': 'User Exists'
    }
    WEIBO_AUTH_FAILED = {
        'err': ERROR_USER + 6,
        'msg': 'Weibo Auth Failed'
    }
    WEIBO_INFO_FAILED = {
        'err': ERROR_USER + 7,
        'msg': 'Get Weibo User Info Failed'
    }


@api.route('/user', methods=['POST'])
def new_user():
    """
## Create new user

    POST /api/user

Parameters:

* `email` (string, required) - email of user (可选如果用户使用手机号码)
* `phone` (int, required) - phone of user (可选如果用户使用电子邮件)
* `password` (string, required) - password of user
* `validation` (string, required) - validation code of this register process, deleted...
Return:

* `userId`: user ID of user

Errors: `1001`, `1005`
    """

    email = request.form.get('email', None)
    phone = request.form.get('phone', None, type=int)
    name = request.form.get('name', None)
    password = request.form.get('password', None)
    #validation = request.form.get('validation', None)

    if email is None and phone is None:
        return jsonify(stat=0, **Error.REGISTER_PARAMETER_INVALID), 403

    if password is None:
        return jsonify(stat=0, **Error.REGISTER_PARAMETER_INVALID), 403

    # if validation is None or validation != "233":
    #     return jsonify(stat=0, **Error.REGISTER_PARAMETER_INVALID), 403

    if email is not None:
        try:
            User.get({
                User.Field.email: email
            })
        except NotFound:
            user_id = User.new_user(email, name, password)
            return jsonify(stat=1, userId=user_id)

    if phone is not None:
        try:
            User.get({
                User.Field.phone: phone
            })
        except NotFound:
            user_id = User.new_user_with_phone(phone, name, password)
            return jsonify(stat=1, userId=user_id)

    # print("email", email);
    # print("phone", phone);
    # print("password", password);
    # print("name", name);
    #print("validation", validation);

    return jsonify(stat=0, **Error.USER_EXISTS), 403


@api.route('/user/<user_id>', methods=['GET'])
def user_info(user_id):
    '''
## 获取用户信息

    GET /user/<user_id>

Returns:

* `userId` (string)
* `avatarUrl` (string)
* `collectionNum` (int)
* `fanNum` (int) - Number of fan
* `followNum` (int) - Number of follow
* `gender` (int)
* `isTeacher` (int) - 1 表示为教师
* `name` (string)
* `phone` (long)
* `place` (dict)
    * `province` (string)
    * `city` (string)
* `school` (string)
* `subscriptionNum` (int) - Number of subscription
* `workNum` (int) - Number of work
* `askNum` (int) - 提问数量
* `commentNum` (int) - 评论数量（只有学生）
* `askMeNum` (int) - 被提问的数量（只有老师）
* `answerNum` (int) - 回答的数量（只有老师）

Errors: `1`
    '''
    try:
        user = User.get({
            User.Field._id: user_id
        }, {
            User.Field.password: 0,
            User.Field.register: 0
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    user.data['userId'] = user.data.get(User.Field._id)
    del user.data[User.Field._id]

    user.data['fanNum'] = len(user.data.get(User.Field.fan, []))
    del user.data[User.Field.fan]

    user.data['followNum'] = len(user.data.get(User.Field.follow, []))
    del user.data[User.Field.follow]

    user.data['subscriptionNum'] = len(user.data.get(User.Field.subscription, []))
    del user.data[User.Field.subscription]

    user.data['collectionNum'] = len(user.data.get(User.Field.collection, []))
    del user.data[User.Field.collection]

    user.data['workNum'] = len(user.data.get(User.Field.workList, []))
    del user.data[User.Field.workList]

    is_teacher = user.data.get(User.Field.isTeacher)

    if is_teacher:
        user.data['answerNum'] = len(user.data.get(User.Field.answerList, []))
        try:
            del user.data[User.Field.answerList]
        except:
            pass

        user.data['askMeNum'] = len(user.data.get(User.Field.askMeList, []))
        try:
            del user.data[User.Field.askMeList]
        except:
            pass
        try:
            studio = Studio.get({
                Studio.Field._id: user.data.get(User.Field.studioId, '')
            }, [
                Studio.Field.name,
                Studio.Field.avatarUrl
            ])
            user.data['studioName'] = studio.data.get(Studio.Field.name)
            user.data['studioAvatarUrl'] = studio.data.get(Studio.Field.avatarUrl)
        except NotFound:
            pass
    else:
        user.data['askNum'] = len(user.data.get(User.Field.askList, []))
        try:
            del user.data[User.Field.askList]
        except:
            pass

        user.data['commentNum'] = len(user.data.get(User.Field.commentList, []))
        try:
            del user.data[User.Field.commentList]
        except:
            pass

    return jsonify(stat=1, user=user.data)


@api.route('/user/login', methods=['POST'])
def user_login():
    """
## Login

    POST /api/user/login

Parameters:

* `account` (string, required)
* `password` (string, required)

Return:

* `userId` (string)
* `avatarUrl` (string)
* `collectionNum` (int)
* `fanNum` (int) - Number of fan
* `followNum` (int) - Number of follow
* `gender` (int)
* `isTeacher` (int)
* `name` (string)
* `phone` (long)
* `place` (dict)
    * `province` (string)
    * `city` (string)
* `school` (string)
* `subscriptionNum` (int) - Number of subscription
* `workNum` (int) - Number of work
* `askNum` (int) - Number of ask, student only
* `commentNum` (int) - Number of comment, student only
* `askMeNum` (int) - Number of ask me, teacher only
* `answerNum` (int) - Number of answer, teacher only

Errors: `1`, `1004`
    """
    account = request.form.get('account', None)
    password = request.form.get('password', None)

    if account is None or password is None:
        return jsonify(stat=0, **Error.LOGIN_PARAMETER_INVALID), 403

    try:
        user = User.get({
            User.Field.email: account
        }, {
            User.Field.register: 0
        })
    except NotFound:
        for ch in account:
            if ch < '0' or ch > '9':
                return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

        try:
            user = User.get({
                User.Field.phone: int(account)
            }, {
                User.Field.register: 0
            })
        except NotFound:
            return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    hashed_password = User.get_hashed_password(password)
    if hashed_password != user.data.get(User.Field.password):
        return jsonify(stat=0, **Error.LOGIN_PARAMETER_INVALID), 403
    del user.data[User.Field.password]

    is_teacher = user.data.get(User.Field.isTeacher)

    user.current_id = user.data[User.Field._id]
    login_user(user, remember=True)

    user.data['userId'] = user.data.get(User.Field._id)
    del user.data[User.Field._id]

    user.data['fanNum'] = len(user.data.get(User.Field.fan, []))
    del user.data[User.Field.fan]

    user.data['followNum'] = len(user.data.get(User.Field.follow, []))
    del user.data[User.Field.follow]

    user.data['subscriptionNum'] = len(user.data.get(User.Field.subscription, []))
    del user.data[User.Field.subscription]

    user.data['collectionNum'] = len(user.data.get(User.Field.collection, []))
    del user.data[User.Field.collection]

    user.data['workNum'] = len(user.data.get(User.Field.workList, []))
    del user.data[User.Field.workList]

    if is_teacher:
        user.data['answerNum'] = len(user.data.get(User.Field.answerList, []))
        try:
            del user.data[User.Field.answerList]
        except:
            pass

        user.data['askMeNum'] = len(user.data.get(User.Field.askMeList, []))
        try:
            del user.data[User.Field.askMeList]
        except:
            pass
    else:
        user.data['askNum'] = len(user.data.get(User.Field.askList, []))
        del user.data[User.Field.askList]

        user.data['commentNum'] = len(user.data.get(User.Field.commentList, []))
        del user.data[User.Field.commentList]

    return jsonify(stat=1, user=user.data)


@api.route('/user/<user_id>', methods=['PUT'])
def update_user_info(user_id):
    """
## update user info

    PUT /api/user/<user_id>

Parameters:

* `avatarUrl` (int, optional) - avatar Url for user
* `gender` (int, optional) - 1 means male, 0 means female, default is 2
* `grade` (int, optional) - 0 表示初中，1表示高一，2表示高二，3表示高三，4表示大学，5表示业余
* `name` (string, optional) - name of user
* `province` (string, optional) - province of user
* `city` (string, optional) - city of user
* `phone` (long, optional) - phone of user, default is 0
* `school` (string, optional) - school of user

Errors: `1002`, `1003`
    """

    query = {}

    avatar_url = request.form.get('avatarUrl', None)
    if avatar_url is not None:
        query[User.Field.avatarUrl] = avatar_url

    gender = request.form.get('gender', 2, type=int)
    if gender != 0 and gender != 1 and gender != 2:
        return jsonify(stat=0, **Error.USER_GENDER_INVALID), 403
    if gender != 2:
        query[User.Field.gender] = gender

    grade = request.form.get('grade', -1, type=int)
    if grade != -1:
        if grade not in [User.Grade.chuzhong, User.Grade.gaoyi,
                         User.Grade.gaoer, User.Grade.gaosan,
                         User.Grade.daxue, User.Grade.yeyu]:
            return jsonify(stat=0, **GlobalError.PARAMETERS_INVALID), 403
        query[User.Field.grade] = grade

    name = request.form.get('name', None)
    if name is not None:
        query[User.Field.name] = name

    province = request.form.get('province', None)
    if province is not None:
        if not query.get(User.Field.place):
            query[User.Field.place] = {}
        query[User.Field.place][User.Place.province] = province

    city = request.form.get('city', None)
    if city is not None:
        if not query.get(User.Field.place):
            query[User.Field.place] = {}
        query[User.Field.place][User.Place.city] = city

    phone = request.form.get('phone', 0, type=int)
    if phone != 0:
        query[User.Field.phone] = phone

    school = request.form.get('school', None)
    if school is not None:
        query[User.Field.school] = school

    if len(query) == 0:
        return jsonify(stat=1)

    try:
        User.collection.update({
            User.Field._id: user_id
        }, {
            '$set': query
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    except:
        return jsonify(stat=0, **Error.INFO_UPDATE_FAILURE), 403

    return jsonify(stat=1)


@api.route('/user/<user_id>/password', methods=['PUT'])
def update_user_password(user_id):
    """
## Update user password

    PUT /api/user/<user_id>/password

Parameters:

* `oldPassword` (string, required) - old password of user
* `newPassword` (string, required) - new password of user

Errors: `1003`
    """
    old_password = request.form.get('oldPassword', None)
    new_password = request.form.get('newPassword', None)
    if old_password is None or new_password is None:
        return jsonify(stat=0, **GlobalError.PARAMETERS_INVALID), 403
    old_hash_password = User.get_hashed_password(old_password)
    new_hash_password = User.get_hashed_password(new_password)
    try:
        user = User.get({
            User.Field._id: user_id
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    if user.data.get(User.Field.password, '') == old_hash_password:
        user.update({
            '$set': {
                User.Field.password: new_hash_password
            }
        })
    else:
        return jsonify(stat=0, **Error.INFO_UPDATE_FAILURE), 403

    return jsonify(stat=1)


# Problem API for student
@api.route('/user/<user_id>/problems', methods=['GET'])
#@login_required
def get_user_problems(user_id):
    '''
## 获取用户所有提问

    GET /api/user/<user_id>/problems

Return:

* `problems` (list of dict)
    * `answerNum` (int) - 被回答的次数
    * `askTo` (string)
    * `askToName` (string)
    * `askToAvatarUrl` (string)
    * `askToType` (int) - 1表示教师，2表示画室
    * `avatarUrl` (string)
    * `commentNum` (int) - 评论数
    * `content` (string) - content of the problem
    * `image` (string) - image of url of the problem
    * `name` (string)
    * `timestamp` (long) - timestamp of the problem
    * `userId` (string)
    * `viewNum` (int) - 被查看次数
    * `zan` (int) - 被赞的数量

Errors: `1`
    '''

    try:
        user = User.get({
            User.Field._id: user_id
        }, [
            User.Field.name,
            User.Field.avatarUrl,
            User.Field.askList
        ])
    except:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    problem_ids = user.data.get(User.Field.askList, [])
    problem_list = Problem.find({
        Problem.Field._id: {
            '$in': problem_ids
        }
    }, [
        Problem.Field.answerNum,
        Problem.Field.askTo,
        Problem.Field.commentNum,
        Problem.Field.content,
        Problem.Field.image,
        Problem.Field.tag,
        Problem.Field.timestamp,
        Problem.Field.viewNum,
        Problem.Field.zan
    ])
    problem_list = dict([(problem[Problem.Field._id], problem) for problem in problem_list])
    problems = []
    for problem_id in problem_ids:
        problem = problem_list.get(problem_id)
        ask_to = get_user_or_studio_from_id(problem.get(Problem.Field.askTo))
        problem['name'] = user.data.get(User.Field.name)
        problem['avatarUrl'] = user.data.get(User.Field.avatarUrl)
        problem['userId'] = user.data.get(User.Field._id)
        problem['askToName'] = ask_to['name']
        problem['askToAvatarUrl'] = ask_to['avatarUrl']
        problem['askToType'] = ask_to['uType']
        problems.append(problem)

    return jsonify(stat=1, problems=problems)


@api.route('/user/<user_id>/problem', methods=['POST'])
def new_user_problem(user_id):
    """
## Create new problem of user

    POST /api/user/<user_id>/problem

Parameters:

* `teacherId` (string, optional) - ID of teacher the problem asks to
* `content` (string, required) - content of post
* `image` (string, optional) - image url
* `tag` (JSON string, required) - JSON 序列化的问题标签列表

Return:

* `problemId`: ID of the new problem

Errors: `1`
    """

    teacher_id = request.form.get('teacherId', '')
    content = request.form.get('content', '')
    image = request.form.get('image', '')
    tag = json.loads(request.form.get('tag'))
    print request.form
    try:
        student = User.get({
            User.Field._id: user_id
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    if teacher_id:
        try:
            teacher = User.get({
                User.Field._id: teacher_id
            })
        except NotFound:
            try:
                teacher = Studio.get({
                    Studio.Field._id: teacher_id
                })
            except NotFound:
                return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    problem_id = Problem.new_problem(teacher_id, content, image, tag,
                                     datetime_to_timestamp(datetime.today()),
                                     user_id)
    image_list = [image] if len(image) > 0 else []
    student.update({
        '$push': {
            User.Field.askList: {
                '$each': [problem_id],
                '$position': 0
            },
            User.Field.workList: {
                '$each': image_list,
                '$position': 0
            }
        }
    })

    if teacher_id:
        teacher.update({
            '$push': {
                User.Field.askMeList: {
                    '$each': [problem_id],
                    '$position': 0
                }
            }
        })

    return jsonify(stat=1, problemId=problem_id)


# Comment API for student
@api.route('/user/<user_id>/comment', methods=['POST'])
def new_user_comment(user_id):
    """
## Post new comment

    POST /api/user/<user_id>/comment

Parameters:

* `replyTo` (string, optional) - user ID of this comment reply to
* `content` (string, required) - content of comment
* `problemId` (string, required) - problem ID of this comment

Return:

* `commentId` - ID of the new comment

Errors: `1`, `2`
    """

    reply_to = request.form.get('replyTo', '')
    content = request.form.get('content', '')
    problem_id = request.form.get('problemId', None)

    try:
        student = User.get({
            User.Field._id: user_id
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    if problem_id is None:
        return jsonify(stat=0, **GlobalError.INVALID_PROBLEM_ID), 403

    try:
        problem = Problem.get({
            Problem.Field._id: problem_id
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_PROBLEM_ID), 403

    comment_id = Comment.new_comment(user_id,
                                     reply_to, content,
                                     datetime_to_timestamp(datetime.today()),
                                     problem_id)
    student.update({
        '$push': {
            User.Field.commentList: comment_id
        }
    })
    problem.update({
        '$push': {
            Problem.Field.commentList: comment_id
        },
        '$inc': {
            Problem.Field.commentNum: 1
        }
    })

    return jsonify(stat=1, commentId=comment_id)


@api.route('/user/<user_id>/comments', methods=['GET'])
def get_user_comments(user_id):
    """
## 获取用户的所有评论

    GET /api/user/<user_id>/comments

Parameters:

* `skip` (int, optional) - 跳过数目，默认为0
* `total` (int, optional) - 返回数目，默认为20

Return:

* `comments` ([dict]) - list of dict, each dictionary contains information of each comment
    * `content` (string) - content of the comment
    * `toUserId` (string) - user reply to
    * `toUserName` (string)
    * `timestamp` (long) - timestamp of the comment
    * `_id` (string) - problem ID the comment belongs
    * `problem` (dict) - 问题详情
        * `answerNum` (int) - 被回答的次数
        * `askTo` (string)
        * `askToName` (string)
        * `askToAvatarUrl` (string)
        * `askToType` (int) - 1表示教师，2表示画室
        * `avatarUrl` (string)
        * `commentNum` (int) - 评论数
        * `content` (string) - content of the problem
        * `image` (string) - image of url of the problem
        * `name` (string)
        * `timestamp` (long) - timestamp of the problem
        * `userId` (string)
        * `viewNum` (int) - 被查看次数
        * `zan` (int) - 被赞的数量

Errors: `1`
    """
    skip = request.args.get('skip', 0, type=int)
    total = request.args.get('total', 20, type=int)
    try:
        student = User.get({
            User.Field._id: user_id
        }, [
            User.Field.commentList
        ])
    except:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    comment_ids = student.data.get(User.Field.commentList, [])
    comment_ids.reverse()
    comment_ids = comment_ids[skip: skip + total]

    comments = []
    for comment_id in comment_ids:
        try:
            comment = Comment.get({
                Comment.Field._id: comment_id
            }, [
                Comment.Field.fromUserId,
                Comment.Field.content,
                Comment.Field.toUserId,
                Comment.Field.timestamp,
                Comment.Field.problemId
            ])
        except NotFound:
            continue
        try:
            problem = Problem.get({
                Problem.Field._id: comment.data.get(Comment.Field.problemId)
            }, [
                Problem.Field.answerNum,
                Problem.Field.askTo,
                Problem.Field.commentNum,
                Problem.Field.content,
                Problem.Field.image,
                Problem.Field.tag,
                Problem.Field.timestamp,
                Problem.Field.userId,
                Problem.Field.viewNum,
                Problem.Field.zan
            ])
            try:
                user = User.get({
                    User.Field._id: problem.data.get(Problem.Field.userId)
                }, [
                    User.Field.name,
                    User.Field.avatarUrl
                ])
                problem.data['name'] = user.data.get(User.Field.name)
                problem.data['avatarUrl'] = user.data.get(User.Field.avatarUrl)
            except NotFound:
                pass
            ask_to = get_user_or_studio_from_id(problem.data.get(Problem.Field.askTo))
            problem.data['askToName'] = ask_to['name']
            problem.data['askToAvatarUrl'] = ask_to['avatarUrl']
            problem.data['askToType'] = ask_to['uType']
        except NotFound:
            continue
        try:
            student = User.get({
                User.Field._id: comment.data.get(Comment.Field.toUserId)
            }, [
                User.Field.name
            ])
            username = student.data.get(User.Field.name)
        except NotFound:
            username = ''
        comments.append({
            Comment.Field.toUserId: comment.data.get(Comment.Field.toUserId),
            'toUserName': username,
            Comment.Field.content: comment.data.get(Comment.Field.content),
            Comment.Field.timestamp: comment.data.get(Comment.Field.timestamp),
            Comment.Field.problemId: comment.data.get(Comment.Field.problemId),
            'problem': problem.data
        })

    return jsonify(stat=1, comments=comments)


# Answer API for teacher
@api.route('/user/<user_id>/answer', methods=['POST'])
def new_user_answer(user_id):
    """
## 教师回答问题

    POST /api/user/<user_id>/answer

Parameters:

* `content` (string, required) - content of answer
* `problemId` (string, required) - ID of problem

Return:

* `answer` (dict) - info of the answer
    """

    content = request.form.get('content', '')
    problem_id = request.form.get('problemId', None)
    a_type = 1

    if problem_id is None:
        return jsonify(stat=0, **GlobalError.INVALID_PROBLEM_ID), 403

    try:
        problem = Problem.get({
            Problem.Field._id: problem_id
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_PROBLEM_ID), 403

    try:
        teacher = User.get({
            User.Field._id: user_id
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    answer_id = Answer.new_answer(user_id, problem_id, content, a_type)
    problem.update({
        '$push': {
            Problem.Field.answerList: answer_id
        },
        '$inc': {
            Problem.Field.answerNum: 1
        }
    })
    teacher.update({
        '$push': {
            User.Field.answerList: {
                '$each': [answer_id],
                '$position': 0
            }
        }
    })

    try:
        answer = Answer.get({
            Answer.Field._id: answer_id
        })
    except:
        print 'Can not find after insert'
        return jsonify(stat=1)

    return jsonify(stat=1, answer=answer.data)


# Problem API for teacher
@api.route('/user/<user_id>/askme', methods=['GET'])
def get_user_ask_me(user_id):
    """
## 获取所有询问该教师的问题

    GET /api/user/<user_id>/askme

Return:

* `problems` ([dict]) - list of dict, each dict are info of problem
    * `_id` (string)
    * `content` (string)
    * `image` (string) - image url of the problem
    * `zan` (int) - the number of zan
    * `viewNum` (int)
    * `answerNum` (int)
    * `timestamp` (long)
    * `userId` (string) - 提问者 ID
    * `name` (string) - name of the user
    * `avatarUrl` (string) - avatar url of the user

Errors: `1`
    """

    try:
        teacher = User.get({
            User.Field._id: user_id
        }, [
            User.Field.askMeList
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    problem_ids = teacher.data.get(User.Field.askMeList, [])
    ask_me = []
    for problem_id in problem_ids:
        problem = Problem.get({
            Problem.Field._id: problem_id
        }, [
            Problem.Field.content,
            Problem.Field.image,
            Problem.Field.zan,
            Problem.Field.viewNum,
            Problem.Field.answerNum,
            Problem.Field.timestamp,
            Problem.Field.userId
        ])
        student = User.get({
            User.Field._id: problem.data.get(Problem.Field.userId)
        }, [
            User.Field.name,
            User.Field.avatarUrl
        ])
        ask_me.append({
            '_id': problem.data.get(Problem.Field._id),
            Problem.Field.content: problem.data.get(Problem.Field.content),
            Problem.Field.image: problem.data.get(Problem.Field.image),
            Problem.Field.zan: problem.data.get(Problem.Field.zan),
            Problem.Field.viewNum: problem.data.get(Problem.Field.viewNum),
            Problem.Field.answerNum: problem.data.get(Problem.Field.answerNum),
            Problem.Field.timestamp: problem.data.get(Problem.Field.timestamp),
            Problem.Field.userId: problem.data.get(Problem.Field.userId),
            User.Field.name: student.data.get(User.Field.name),
            User.Field.avatarUrl: student.data.get(User.Field.avatarUrl)
        })

    return jsonify(stat=1, problems=ask_me)


@api.route('/user/weibo/auth', methods=['GET'])
def weibo_oauth_callback():
    '''
## 使用微博登录

    GET /api/user/weibo/auth

Parameters:

* `CODE`

Return:

* `userId` (string)
* `avatarUrl` (string)
* `collectionNum` (int)
* `fanNum` (int) - Number of fan
* `followNum` (int) - Number of follow
* `gender` (int)
* `isTeacher` (int)
* `name` (string)
* `phone` (long)
* `place` (dict)
    * `province` (string)
    * `city` (string)
* `school` (string)
* `subscriptionNum` (int) - Number of subscription
* `workNum` (int) - Number of work
* `askNum` (int) - Number of ask, student only
* `commentNum` (int) - Number of comment, student only
* `askMeNum` (int) - Number of ask me, teacher only
* `answerNum` (int) - Number of answer, teacher only

Errors: `1006`, `1007`
    '''
    code = request.args.get('code', None)
    token_info = get_weibo_access_token(code)

    access_token = token_info.get('access_token', None)
    uid = token_info.get('uid', None)
    if access_token is None or uid is None:
        return jsonify(stat=0, token_info=token_info, args=request.args, **Error.WEIBO_AUTH_FAILED), 403

    user_info = get_weibo_info(uid, access_token)
    name = user_info.get('name', None)
    if name is None:
        return jsonify(stat=0, **Error.WEIBO_INFO_FAILED), 403

    avatar_url = user_info.get('profile_image_url', None)
    if avatar_url is None:
        avatar_url = ''

    try:
        user = User.get({
            User.Field.name: name
        }, {
            User.Field.password: 0,
            User.Field.register: 0
        })
    except NotFound:
        user_id = User.new_user_from_weibo(uid, name, avatar_url, access_token)
        user = User.get({User.Field._id: user_id})

    user.data['userId'] = user.data.get(User.Field._id)
    del user.data[User.Field._id]

    user.data['fanNum'] = len(user.data.get(User.Field.fan, []))
    del user.data[User.Field.fan]

    user.data['followNum'] = len(user.data.get(User.Field.follow, []))
    del user.data[User.Field.follow]

    user.data['subscriptionNum'] = len(user.data.get(User.Field.subscription, []))
    del user.data[User.Field.subscription]

    user.data['collectionNum'] = len(user.data.get(User.Field.collection, []))
    del user.data[User.Field.collection]

    user.data['workNum'] = len(user.data.get(User.Field.workList, []))
    del user.data[User.Field.workList]

    is_teacher = user.data.get(User.Field.isTeacher)

    if is_teacher:
        user.data['answerNum'] = len(user.data.get(User.Field.answerList, []))
        try:
            del user.data[User.Field.answerList]
        except:
            pass

        user.data['askMeNum'] = len(user.data.get(User.Field.askMeList, []))
        try:
            del user.data[User.Field.askMeList]
        except:
            pass
    else:
        user.data['askNum'] = len(user.data.get(User.Field.askList, []))
        del user.data[User.Field.askList]

        user.data['commentNum'] = len(user.data.get(User.Field.commentList, []))
        del user.data[User.Field.commentList]

    return jsonify(stat=1, user=user.data)


@api.route('/user/<from_user_id>/follow', methods=['POST'])
def update_user_follow(from_user_id):
    '''
## 关注用户

    POST /api/user/<from_user_id>/follow

Parameters:

* `userId` (string, required) - 被关注者 ID
* `follow` (int, optional) - 1 表示关注，0 表示取消关注
    '''
    user_id = request.form.get('userId', None)
    follow = request.form.get('follow', 1, type=int)
    try:
        from_user = User.get({
            User.Field._id: from_user_id
        }, [
            User.Field.follow
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    if follow == 1 and user_id in from_user.data.get(User.Field.follow):
        return jsonify(stat=1)

    try:
        to_user = User.get({
            User.Field._id: user_id
        })
    except:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    action = '$push' if follow == 1 else '$pull'
    if follow == 1:
        action_query = {
            User.Field.follow: {
                '$each': [user_id],
                '$position': 0
            }
        }
    else:
        action_query = {
            User.Field.follow: user_id
        }

    from_user.update({
        action: action_query
    })

    if follow == 1:
        action_query = {
            User.Field.fan: {
                '$each': [from_user_id],
                '$position': 0
            }
        }
    else:
        action_query = {
            User.Field.fan: from_user_id
        }

    to_user.update({
        action: action_query
    })

    return jsonify(stat=1)


@api.route('/user/<user_id>/follow', methods=['GET'])
def get_user_follow(user_id):
    '''
## 获取用户关注的用户

    GET /api/user/<user_id>/follow

Parameters:

* `skip` (int, optional) - 跳过多少人，默认为 0
* `total` (int, optional) - 返回多少人，默认为 20
* `userId` (string, optional) - 当前登录着的用户 ID

Return:

* `follow` (list of dict) - 所关注的人的列表，每个元素是一个字典
    * `_id` (string)
    * `name` (string)
    * `avatarUrl` (string)
    * `relation` (int) - 当前登录用户与这个用户的关系，0表示没关注，1表示当前登录用户关注这个用户，2表示这个用户关注着当前登录用户，3表示互相关注
    * `uType` (int) - 0表示普通学生，1表示教师，2表示画室
    '''
    skip = request.args.get('skip', 0, type=int)
    total = request.args.get('total', 20, type=int)
    _id = request.args.get('userId', None)
    try:
        user = User.get({
            User.Field._id: user_id
        }, [
            User.Field.follow
        ])
    except:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    follow = []
    follow_id = user.data.get(User.Field.follow, [])[skip: skip + total]
    for u_id in follow_id:
        u_type = 0
        try:
            u_user = User.get({
                User.Field._id: u_id
            }, [
                User.Field.avatarUrl,
                User.Field.name,
                User.Field.fan,
                User.Field.follow,
                User.Field.isTeacher
            ])
            if u_user.data.get(User.Field.isTeacher):
                u_type = 1
        except NotFound:
            try:
                u_user = Studio.get({
                    Studio.Field._id: u_id
                }, [
                    Studio.Field.avatarUrl,
                    Studio.Field.name,
                    Studio.Field.fan,
                    Studio.Field.follow
                ])
                u_type = 2
            except NotFound:
                continue
        relation = 0
        if _id and _id in u_user.data.get(User.Field.fan, []):
            relation += 1
        if _id and _id in u_user.data.get(User.Field.follow, []):
            relation += 2
        follow.append({
            User.Field._id: u_id,
            User.Field.name: u_user.data.get(User.Field.name),
            User.Field.avatarUrl: u_user.data.get(User.Field.avatarUrl),
            'relation': relation,
            'uType': u_type
        })

    return jsonify(stat=1, follow=follow)


@api.route('/user/<user_id>/fan', methods=['GET'])
def get_user_fan(user_id):
    '''
## 获取用户的粉丝

    GET /api/user/<user_id>/fan

Parameters:

* `skip` (int, optional) - 跳过多少人，默认为 0
* `total` (int, optional) - 返回多少人，默认为 20
* `userId` (string, optional) - 当前登录着的用户 ID

Return:

* `fan` (list of dict) - 粉丝的列表，每个元素是一个字典
    * `_id` (string)
    * `name` (string)
    * `avatarUrl` (string)
    * `relation` (int) - 当前登录用户与这个粉丝的关系，0表示没关注，1表示当前登录用户关注这个用户，2表示这个用户关注着当前登录用户，3表示互相关注
    * `uType` (int) - 0表示普通学生，1表示教师，2表示画室
    '''
    skip = request.args.get('skip', 0, type=int)
    total = request.args.get('total', 20, type=int)
    _id = request.args.get('userId', None)
    try:
        user = User.get({
            User.Field._id: user_id
        }, [
            User.Field.fan
        ])
    except:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    fan = []
    fan_ids = user.data.get(User.Field.fan, [])[skip: skip + total]
    for u_id in fan_ids:
        u_type = 0
        try:
            u_user = User.get({
                User.Field._id: u_id
            }, [
                User.Field.avatarUrl,
                User.Field.name,
                User.Field.fan,
                User.Field.follow,
                User.Field.isTeacher
            ])
            if u_user.data.get(User.Field.isTeacher):
                u_type = 1
        except NotFound:
            try:
                u_user = Studio.get({
                    Studio.Field._id: u_id
                }, [
                    Studio.Field.avatarUrl,
                    Studio.Field.name,
                    Studio.Field.fan,
                    Studio.Field.follow
                ])
                u_type = 2
            except NotFound:
                continue
        relation = 0
        if _id and _id in u_user.data.get(User.Field.fan, []):
            relation += 1
        if _id and _id in u_user.data.get(User.Field.follow, []):
            relation += 2
        fan.append({
            User.Field._id: u_id,
            User.Field.name: u_user.data.get(User.Field.name),
            User.Field.avatarUrl: u_user.data.get(User.Field.avatarUrl),
            'relation': relation,
            'uType': u_type
        })

    return jsonify(stat=1, fan=fan)


@api.route('/user/<user_id>/studio', methods=['PUT' , 'DELETE'])
def update_user_studio(user_id):
    '''
## 关注画室

    关注 PUT /api/user/<user_id>/studio
    取消关注 DELETE /api/user/<user_id>/studio

Parameters:

* `studioId` (string, required) - 被关注画室 ID
    '''
    studio_id = request.form.get('studioId', None) or request.args.get('studioId', None)
    try:
        user = User.get({
            User.Field._id: user_id
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    try:
        studio = Studio.get({
            Studio.Field._id: studio_id
        }, [
            Studio.Field.fan
        ])
    except:
        return jsonify(stat=0, **GlobalError.INVALID_STUDIO_ID), 403

    if request.method == 'PUT' and user_id in studio.data.get(Studio.Field.fan, []):
        return jsonify(stat=1)

    if request.method == 'DELETE' and user_id not in studio.data.get(Studio.Field.fan, []):
        return jsonify(stat=1)

    if request.method == 'PUT':
        action_query = {
            '$push': {
                Studio.Field.fan: {
                    '$each': [user_id],
                    '$position': 0
                }
            },
            '$inc': {
                Studio.Field.fanNum: 1
            }
        }
    else:
        action_query = {
            '$pull': {
                Studio.Field.fan: user_id
            },
            '$inc': {
                Studio.Field.fanNum: -1
            }
        }

    studio.update(action_query)

    if request.method == 'PUT':
        action_query = {
            '$push': {
                User.Field.follow: {
                    '$each': [studio_id],
                    '$position': 0
                }
            }
        }
    else:
        action_query = {
            '$pull': {
                User.Field.follow: studio_id
            }
        }

    user.update(action_query)
    return jsonify(stat=1)


@api.route('/user/name', methods=['GET'])
def find_user_by_name():
    '''
## 通过用户名获取用户详情

    GET /api/user/name

Parameters:

* `name` (string, required)

Return:

* `users` (list of dict)
    * `avatarUrl` (string)
    * `name` (string)
    * `userId` (string)
    '''
    name = request.args.get('name', None)
    if name is None:
        return jsonify(stat=0, **GlobalError.PARAMETERS_INVALID), 403
    try:
        user_list = User.find({
            User.Field.name: {
                '$regex': name
            }
        }, [
            User.Field.name,
            User.Field.avatarUrl
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.PARAMETERS_INVALID), 403

    users = []

    for user in user_list:
        users.append({
            'userId': user[User.Field._id],
            'name': user[User.Field.name],
            'avatarUrl': user[User.Field.avatarUrl]
        })

    return jsonify(stat=1, users=users)


@api.route('/user/<user_id>/collection', methods=['GET'])
def get_user_collection(user_id):
    '''
## 获取用户收藏

    GET /api/user/<user_id>/collection

Parameters:

* `skip` (int, optional) - 跳过数目，默认为0
* `total` (int, optional) - 返回总数目，默认为20

Return:

* `collection` (list of string) - 图片链接列表
    '''
    skip = request.args.get('skip', 0, type=int)
    total = request.args.get('total', 20, type=int)
    try:
        user = User.get({
            User.Field._id: user_id
        }, [
            User.Field.collection
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    return jsonify(stat=1, collection=user.data.get(User.Field.collection, [])[skip:skip + total])


@api.route('/user/<user_id>/collection', methods=['PUT', 'DELETE'])
def update_user_collection(user_id):
    '''
## 更新收藏

    添加 PUT /api/user/<user_id>/collection
    删除 DELETE /api/user/<user_id>/collection

Parameters:

* `imageUrl` (string, required) - 图片连接
    '''
    image_url = request.form.get('imageUrl', None) or request.args.get('imageUrl', None)
    if image_url is None:
        return jsonify(stat=0, **GlobalError.PARAMETERS_INVALID), 403

    action = '$push' if request.method == 'PUT' else '$pull'
    try:
        user = User.get({
            User.Field._id: user_id
        }, [
            User.Field.collection
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    if action == '$push' and image_url in user.data.get(User.Field.collection):
        return jsonify(stat=1)
    try:
        User.collection.update({
            User.Field._id: user_id
        }, {
            action: {
                User.Field.collection: image_url
            }
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    except:
        pass
    return jsonify(stat=1)


@api.route('/user/<user_id>/subscription', methods=['GET'])
def get_user_subscription(user_id):
    '''
## 获取用户订阅

    GET /api/user/<user_id>/subscription

Parameters:

* `skip` (int, optional) - 跳过数目，默认为0
* `total` (int, optional) - 返回总数目，默认为20

Return:

* `subscription` (list of dict) - 订阅的画室信息列表
    * `studioId` (string)
    * `name` (string)
    * `avatarUrl` (string)
    * `description` (string)
    '''
    skip = request.args.get('skip', 0, type=int)
    total = request.args.get('total', 20, type=int)
    try:
        user = User.get({
            User.Field._id: user_id
        }, [
            User.Field.subscription
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    studio_ids = user.data.get(User.Field.subscription, [])[skip:skip + total]
    subscription = []
    for studio_id in studio_ids:
        try:
            studio = Studio.get({
                Studio.Field._id: studio_id
            }, [
                Studio.Field.name,
                Studio.Field.avatarUrl,
                Studio.Field.description
            ])
        except NotFound:
            continue
        subscription.append({
            'studioId': studio_id,
            Studio.Field.name: studio.data.get(Studio.Field.name),
            Studio.Field.avatarUrl: studio.data.get(Studio.Field.avatarUrl),
            Studio.Field.description: studio.data.get(Studio.Field.description)
        })
    return jsonify(stat=1, subscription=subscription)


@api.route('/user/<user_id1>/relation/<user_id2>', methods=['GET'])
def get_user_relation(user_id1, user_id2):
    '''
## 查询 user_id1 与 user_id2 的关系

    GET /api/user/<user_id1>/relation/<user_id2>

Return:

* `relation` (int) - 0表示无关系，1表示user_id1关注user_id2，2表示user_id2是user_id1的粉丝，3表示user_id1与user_id2互相关注
    '''
    try:
        user1 = User.get({
            User.Field._id: user_id1
        }, [
            User.Field.follow,
            User.Field.fan
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    relation = 0
    if user_id2 in user1.data.get(User.Field.follow):
        relation += 1
    if user_id2 in user1.data.get(User.Field.fan):
        relation += 2

    return jsonify(stat=1, relation=relation)


@api.route('/user/<user_id>/work', methods=['GET'])
def get_user_work(user_id):
    '''
## 获取用户作品

    GET /api/user/<user_id>/work

Parameters:

* `skip` (int, optional) - 跳过数目，默认为0
* `total` (int, optional) - 返回总数目，默认为20

Return:

* `work` (list of string) - 图片链接列表
    '''
    skip = request.args.get('skip', 0, type=int)
    total = request.args.get('total', 20, type=int)
    try:
        user = User.get({
            User.Field._id: user_id
        }, [
            User.Field.workList
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    return jsonify(stat=1, work=user.data.get(User.Field.workList, [])[skip:skip + total])


@api.route('/user/<user_id>/work', methods=['PUT', 'DELETE'])
def update_user_work(user_id):
    '''
## 更新用户作品

    添加 PUT /api/user/<user_id>/work
    删除 DELETE /api/user/<user_id>/work

Parameters:

* `imageUrl` (string, required) - 图片连接
    '''
    image_url = request.form.get('imageUrl', None) or request.args.get('imageUrl', None)
    if image_url is None and image_url:
        return jsonify(stat=0, **GlobalError.PARAMETERS_INVALID), 403

    action = '$push' if request.method == 'PUT' else '$pull'
    try:
        User.collection.update({
            User.Field._id: user_id
        }, {
            action: {
                User.Field.workList: image_url
            }
        })
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403
    except:
        pass
    return jsonify(stat=1)


@api.route('/user/<user_id>/studio-comment', methods=['POST'])
def new_user_studio_comment(user_id):
    '''
## 用户评论画室

    POST /api/user/<user_id>/studio-comment

Parameters:

* `content` (string, required) - 评论内容
* `studioId` (string, required) - 画室ID

Return:

* `studioCommentId` (string)
    '''
    try:
        user = User.get({User.Field._id: user_id}, [])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_USER_ID), 403

    content = request.form.get('content', None)
    studio_id = request.form.get('studioId', None)
    if content is None or studio_id is None:
        return jsonify(stat=0, **GlobalError.PARAMETERS_INVALID), 403

    studio_comment_id = StudioComment.new_studio_comment(user_id, content, studio_id)
    return jsonify(stat=1, studioCommentId=studio_comment_id)


@api.route('/user/<user_id>/answer', methods=['GET'])
def get_user_answer(user_id):
    """
## 获取所有该用户已回答问题

    GET /api/user/<user_id>/answer

Return:

* `problems` ([dict]) - list of dict
    * `_id` (string)
    * `answer` (string)
    * `answerId` (string)
    * `answerNum` (int)
    * `askTo` (string)
    * `askToAvatarUrl` (string)
    * `askToName` (string)
    * `askToType` (int) - 1表示教师，2表示画室，-1表示无
    * `commentNum` (int)
    * `content` (string)
    * `image` (string) - image url of the problem
    * `zan` (int) - the number of zan
    * `viewNum` (int)
    * `answerNum` (int)
    * `timestamp` (long)
    * `userId` (string) - 提问者 ID
    * `name` (string) - name of the user
    * `avatarUrl` (string) - avatar url of the user

Errors: `1`
    """

    try:
        user = User.get({
            Studio.Field._id: user_id
        }, [
            User.Field.answerList
        ])
    except NotFound:
        return jsonify(stat=0, **GlobalError.INVALID_STUDIO_ID), 403

    answer_ids = user.data.get(User.Field.answerList, [])
    answer_list = Answer.find({
        Answer.Field._id: {
            '$in': answer_ids
        }
    })
    answer_list = dict([(answer[Answer.Field._id], answer) for answer in answer_list])
    answer_list = dict([(answer_id, answer_list[answer_id]) for answer_id in answer_ids])
    answers = []
    for answer_id in answer_list:
        answer = answer_list[answer_id]
        problem = Problem.get({
            Problem.Field._id: answer.get(Answer.Field.problemId)
        }, [
            Problem.Field.content,
            Problem.Field.image,
            Problem.Field.zan,
            Problem.Field.viewNum,
            Problem.Field.answerNum,
            Problem.Field.askTo,
            Problem.Field.commentNum,
            Problem.Field.tag,
            Problem.Field.timestamp,
            Problem.Field.userId
        ])
        student = User.get({
            User.Field._id: problem.data.get(Problem.Field.userId)
        }, [
            User.Field.name,
            User.Field.avatarUrl
        ])
        ask_to = get_user_or_studio_from_id(problem.data.get(Problem.Field.askTo))
        answers.append({
            '_id': problem.data.get(Problem.Field._id),
            'answer': answer.get(Answer.Field.content)[0].get(Answer.Content.content),
            'answerId': answer_id,
            'askTo': problem.data.get(Problem.Field.askTo),
            'askToAvatarUrl': ask_to.get('avatarUrl'),
            'askToName': ask_to.get('name'),
            'askToType': ask_to.get('uType'),
            Problem.Field.answerNum: problem.data.get(Problem.Field.answerNum),
            Problem.Field.commentNum: problem.data.get(Problem.Field.commentNum),
            Problem.Field.content: problem.data.get(Problem.Field.content),
            Problem.Field.image: problem.data.get(Problem.Field.image),
            User.Field.avatarUrl: student.data.get(User.Field.avatarUrl),
            User.Field.name: student.data.get(User.Field.name),
            Problem.Field.tag: problem.data.get(Problem.Field.tag),
            Problem.Field.timestamp: problem.data.get(Problem.Field.timestamp),
            Problem.Field.userId: problem.data.get(Problem.Field.userId),
            Problem.Field.viewNum: problem.data.get(Problem.Field.viewNum),
            Problem.Field.zan: problem.data.get(Problem.Field.zan)
        })

    return jsonify(stat=1, problems=answers)


@api.route('/search', methods=['POST'])
def search():
    pass

@api.route('/register', methods=['GET', 'POST'])
def tregister():
    return render_template('register.html')

from flask import render_template
@api.route('/login')
def tlogin():
    return render_template('login.html',
                           title='Login')

@api.route('/user/logout')
#@login_required
def user_logout():
    logout_user()
    return jsonify(stat=1)

@api.route('/user/forget_pass', methods=['POST'])
def forget_pass():
    """
## 忘记密码接口
Parameters: 
`phone`: 电话号码
`password`: 新密码
    """
    phone = request.form.get('phone', None, type=int)
    password = request.form.get('password', None)

    if (phone is not None) and (password is not None):
        try:
            user = User.get(
                {User.Field.phone: phone}
            )
            # user = User.find({
            #         User.Field.phone: phone
            #     })
            # print('haha', user)
            user.update(
                {
                    '$set': {
                        User.Field.password: User.get_hashed_password(password)
                    }
                }
            )
            return jsonify(stat=1)
        except NotFound:
            return jsonify(stat=0, **Error.USER_EXISTS), 403

    return jsonify(stat=0, **Error.USER_EXISTS), 403

@api.route('/test')
def test():
    return render_template('forget_pass.html')

